<?php

namespace app\admin\controller\yungift\gift;

use addons\yungift\library\Super;
use addons\yungift\model\Activity;
use addons\yungift\model\Config;
use addons\yungift\model\ImportLog as ImportLogModel;
use addons\yungift\library\Logic;
use addons\yungift\library\Constant;
use addons\yungift\model\FundRecord;
use addons\yungift\model\FundUser;
use addons\yungift\model\GiftMain;
use addons\yungift\model\GiftOrder;
use app\admin\model\yungift\CardCode;
use app\admin\model\yungift\CardMain;
use app\admin\model\yungift\GiftCode;
use app\admin\model\yungift\GiftSpec;
use app\common\controller\Backend;
use fast\Random;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use think\Db;
use think\Exception;
use think\exception\PDOException;
use think\exception\ValidateException;

/**
 * 礼品 - 兑换订单
 */
class Order extends Backend
{
    public $noNeedRight = ['typeModel'];

    /**
     * @var GiftOrder
     */
    protected $model;

    // 联表查询，解决字段冲突
    protected $relationSearch = true;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new GiftOrder();
    }

    /**
     * 查看
     */
    public function index()
    {
        $modelId = $this->request->request('model_id');
        $modelType = $this->request->request('model_type');
        $modelAccount = $this->request->request('model_account');
        $giftId = $this->request->request('gift_id');
        $giftCodeId = $this->request->request('gift_code_id');
        if ($this->request->isAjax()) {
            // 重载查询条件
            $filter = $this->request->get('filter');
            $op = $this->request->get('op');
            list($filter, $op) = $this->formatFilterOp($filter, $op);
            $this->request->get(['filter' => $filter, 'op' => $op]);

            // 通用查询条件
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
            $query = $this->model
                ->field('gift_order.*')
                ->with(['cardCodeData'])
                ->where($where)
                ->where('gift_order.deleted_at is null');
            if ($modelId) {
                $query->where(['type' => $modelType, 'model_id' => $modelId]);
            }
            if ($modelAccount) {
                $query->where(['type' => $modelType, 'account_id' => $modelAccount]);
            }
            if ($giftId) {
                $query->where(['gift_id' => $giftId]);
            }
            if ($giftCodeId) {
                $query->where(['gift_code_id' => $giftCodeId]);
            }
            $list = $query->order($sort, $order)->limit($offset, $limit)->paginate($limit);
            foreach ($list as $item) {
                $item->append(['gift_data_array', 'type_text', 'model_text'])->hidden(['gift_data']);
                if ($item->cardCodeData) {
                    $item->card_number = $item->cardCodeData->number;
                } else {
                    $item->card_number = '-';
                }
                unset($item->cardCodeData);
                unset($item->card_code_data);

            }
            $result = array(
                'total' => $list->total(),
                'rows'  => $list->items(),
            );

            return json($result);
        }

        $this->assignconfig('modelId', $modelId);
        $this->assignconfig('modelType', $modelType);
        $this->assignconfig('modelAccount', $modelAccount);
        $this->assignconfig('giftId', $giftId);

        // 活动列表
        $activityList = Activity::getOptionList();
        $this->view->assign('activityList', $activityList);
        $this->assignconfig('activityList', $activityList);

        // 礼卡列表
        $cardList = CardMain::getOptionList();
        $this->view->assign('cardList', $cardList);
        $this->assignconfig('cardList', $cardList);

        // 礼品列表
        $giftList = GiftMain::getOptionList();
        $this->view->assign('giftList', $giftList);
        $this->assignconfig('giftList', $giftList);

        // 礼品类型
        $giftTypeList = GiftOrder::getGiftTypeList();
        $this->view->assign('giftTypeList', $giftTypeList);
        $this->assignconfig('giftTypeList', $giftTypeList);

        // 领取方式
        $gainMethodList = GiftOrder::getGainMethodList();
        $this->view->assign('gainMethodList', $gainMethodList);
        $this->assignconfig('gainMethodList', $gainMethodList);

        // 类型
        $this->view->assign('typeList', $this->model::getTypeList());
        $this->assignconfig('typeList', $this->model::getTypeList());

        // 状态
        $this->view->assign('statusList', $this->model::getStatusList());
        $this->assignconfig('statusList', $this->model::getStatusList());

        return $this->view->fetch();
    }

    /**
     * 格式化查询条件
     *
     * @param $filter
     * @param $op
     * @return array
     */
    private function formatFilterOp($filter, $op)
    {
        $filter = json_decode($filter, true);
        $op = json_decode($op, true);

        return [json_encode($filter), json_encode($op)];
    }

    /**
     * 联动搜索
     */
    public function typeModel()
    {
        $group = $this->request->get('group');
        $source = $this->request->get('source');

        $list = [];
        if ($group === 'type') {
            foreach (GiftOrder::getTypeList() as $key => $value) {
                $list[] = ['value' => $key, 'name' => $value];
            }
        } elseif ($group === 'model') {
            if ($source === 'activity') {
                $list = Activity::field('id as value, name')->select();
            } elseif ($source === 'card') {
                $list = CardMain::field('id as value, name')->select();
            }
        }
        $this->success('', null, $list);
    }

    /**
     * 详情
     */
    public function detail($ids)
    {
        if (! $row = $this->model::get(['id' => $ids])) {
            $this->error(__('No Results were found'));
        }
        if ($this->request->isAjax()) {
            $this->success('Ajax请求成功', null, ['id' => $ids]);
        }
        $this->view->assign('row', $row);

        $giftData = json_decode($row->gift_data, true);
        $this->view->assign('giftData', $giftData);

        $giftCode = $giftData['code_data']['data'] ?? '';
        $this->view->assign('codeMix', Super::stringHide($giftCode));

        $trackInfo = [];
        if ($row->status == GiftOrder::STATUS_HAS_DEPLOY && $row->gain_method == GiftOrder::GAIN_METHOD_EXPRESS) {
            try {
                $trackInfo = Logic::queryExpressTrack($row->express_company, $row->express_number, $row->express_phone);
            } catch (Exception $e) {
                $this->error(__($e->getMessage()));
            }

        }
        $this->view->assign('trackInfo', $trackInfo);

        return $this->view->fetch();
    }

    /**
     * 发货
     */
    public function deploy($ids)
    {
        if (! $row = $this->model::get(['id' => $ids])) {
            $this->error(__('No Results were found'));
        }
        if ($this->request->isPost()) {
            $params = $this->request->post("row/a");
            if ($params) {
                if ($params['gain_method'] == GiftOrder::GAIN_METHOD_EXPRESS) {
                    if (! Config::getGroupAttribute(Config::GROUP_EXPRESS, 'aliyun_appcode')) {
                        $this->error(__('快递设置的"物流插件appcode"不能为空'));
                    }
                    if (empty($params['express_company'])) {
                        $this->error(__('快递公司不能为空'));
                    }
                    if (empty($params['express_number'])) {
                        $this->error(__('快递单号不能为空'));
                    }
                    if ($params['express_company'] === 'SF') {
                        if (empty($params['express_phone'])) {
                            $this->error(__('顺丰必须填写手机号，才能查询物流信息'));
                        }
                    }
                }
                $result = false;
                Db::startTrans();
                try {
                    // 是否采用模型验证
                    if ($this->modelValidate) {
                        $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                        $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.deploy' : $name) : $this->modelValidate;
                        $row->validateFailException(true)->validate($validate);
                    }
                    $row->status = GiftOrder::STATUS_HAS_DEPLOY;
                    $row->deployed_at = time();
                    $result = $row->allowField(true)->save($params);
                    Db::commit();
                } catch (ValidateException | PDOException | Exception $e) {
                    Db::rollback();
                    $this->error($e->getMessage());
                }
                if ($result !== false) {
                    Logic::sendDeployMessage($row->id);  // 发送发货消息
                    $this->success();
                } else {
                    $this->error(__('No rows were updated'));
                }
            }
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $this->view->assign('row', $row);

        // 领取方式
        $gainMethodList = GiftOrder::getGainMethodList(true);
        $this->view->assign('gainMethodList', $gainMethodList);

        // 快递公司列表
        $giftList = Logic::queryExpressCompany();
        $this->view->assign('companyList', $giftList);

        return $this->view->fetch();
    }

    /**
     * 编辑
     */
    public function change($ids)
    {
        if (! $row = $this->model::get(['id' => $ids])) {
            $this->error(__('No Results were found'));
        }
        if ($this->request->isPost()) {
            $params = $this->request->post("row/a");
            if ($params) {
                if ($row->status == GiftOrder::STATUS_HAS_DEPLOY && $params['gain_method'] == GiftOrder::GAIN_METHOD_EXPRESS) {
                    if (! Config::getGroupAttribute(Config::GROUP_EXPRESS, 'aliyun_appcode')) {
                        $this->error(__('快递设置的"物流插件appcode"不能为空'));
                    }
                    if (empty($params['express_company'])) {
                        $this->error(__('快递公司不能为空'));
                    }
                    if (empty($params['express_number'])) {
                        $this->error(__('快递单号不能为空'));
                    }
                    if ($params['express_company'] === 'SF') {
                        if (empty($params['express_phone'])) {
                            $this->error(__('顺丰必须填写手机号，才能查询物流信息'));
                        }
                    }
                }
                $result = false;
                Db::startTrans();
                try {
                    // 是否采用模型验证
                    if ($this->modelValidate) {
                        $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                        $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
                        $row->validateFailException(true)->validate($validate);
                    }
                    $result = $row->allowField(true)->save($params);
                    Db::commit();
                } catch (ValidateException | PDOException | Exception $e) {
                    Db::rollback();
                    $this->error($e->getMessage());
                }
                if ($result !== false) {
                    $this->success();
                } else {
                    $this->error(__('No rows were updated'));
                }
            }
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $this->view->assign('row', $row);

        // 领取方式
        $gainMethodList = GiftOrder::getGainMethodList(true);
        $this->view->assign('gainMethodList', $gainMethodList);

        // 快递公司列表
        $giftList = Logic::queryExpressCompany();
        $this->view->assign('companyList', $giftList);

        return $this->view->fetch();
    }

    /**
     * 取消
     */
    public function cancel($ids)
    {
        if (! $this->request->isPost()) {
            $this->error(__('Invalid parameters'));
        }
        $ids = $ids ?: $this->request->post('ids');
        if ($ids) {
            $pk = $this->model->getPk();
//            $adminIds = $this->getDataLimitAdminIds();
//            if (is_array($adminIds)) {
//                $this->model->where($this->dataLimitField, 'in', $adminIds);
//            }
            $dataList = $this->model->where($pk, 'in', $ids)
                ->where('status', '<>', GiftOrder::STATUS_HAS_BACK)->select();
            foreach ($dataList as $item) {
                Db::startTrans();
                try {
                    // 订单
                    $giftOrder = GiftOrder::where(['id' => $item->id])->lock(true)->find();
                    $giftOrder->status = GiftOrder::STATUS_HAS_BACK;
                    $giftOrder->save();

                    // 快照
                    $giftData = json_decode($item->gift_data, true);

                    // 礼品
                    $gift = GiftMain::where(['id' => $item->gift_id])->lock(true)->find();
                    if (! $gift || $gift['type'] != $giftData['type'] || ($gift->multi_spec && ! $item->gift_spec_id)) {
                        throw new Exception($giftData['name'] . '礼品变更过，不能进行取消退回');
                    }
                    $gift->count_left++;
                    $gift->count_gain--;
                    $gift->save();

                    // 规格
                    if ($item->gift_spec_id) {
                        $giftSpec = GiftSpec::where(['id' => $item->gift_spec_id])->lock(true)->find();
                        if (! $giftSpec) {
                            throw new Exception($giftData['spec_data']['name'] . '规格被删除，不能进行取消退回');
                        }
                        $giftSpec->count_left++;
                        $giftSpec->count_gain--;
                        $giftSpec->save();
                    }

                    // 券码
                    if ($item->gift_code_id) {
                        $giftCode = GiftCode::where(['id' => $item->gift_code_id])->lock(true)->find();
                        if (! $giftCode) {
                            throw new Exception($giftData['code'] . '券码被删除，不能进行取消退回');
                        }
                        $giftCode->status = GiftCode::STATUS_NORMAL;
                        $giftCode->save();
                    }

                    if ($giftOrder['type'] === GiftOrder::TYPE_ACTIVITY) {
                        // 礼币
                        FundUser::amountCounter($item->model_id, $item->member_id, FundRecord::ACTION_GIFT_BACK,
                            $item->amount, Logic::SOURCE_GIFT_RECORD, $item->id, $item->account_id);
                    } elseif ($giftOrder['type'] === GiftOrder::TYPE_CARD) {
                        // 卡密
                        $cardCode = CardCode::where(['id' => $item->account_id])->lock(true)->find();
                        if (! $cardCode) {
                            throw new Exception('礼卡密被删除，不能进行取消退回');
                        }
                        $cardCode->chance_use--;
                        $cardCode->save();
                    }
                    Db::commit();
                } catch (PDOException | Exception $e) {
                    Db::rollback();
                    $this->error($e->getMessage());
                }
            }
            $this->success();
        }
        $this->error(__('Parameter %s can not be empty', 'ids'));
    }

    /**
     * 数据导入
     *
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
     */
    public function import()
    {
        // 超时、超内存设置
        ini_set('memory_limit', '1024M');
        ini_set('max_execution_time', '0');

        // 获取文件路径
        $file = $this->request->request('file');
        if (! $file) {
            $this->error(__('Parameter %s can not be empty', 'file'));
        }
        $filePath = ROOT_PATH . DS . 'public' . DS . $file;
        if (! is_file($filePath)) {
            $this->error(__('No results were found'));
        }

        // 新增导入结果
        ImportLogModel::create([
            'scene'       => ImportLogModel::SCENE_GIFT_DEPLOY,
            'import_file' => $file,
            'status'      => ImportLogModel::STATUS_HANDLE
        ]);

        // 实例化reader，并读取文件
        $ext = pathinfo($filePath, PATHINFO_EXTENSION);
        if ($ext !== 'xlsx') {
            $this->error(__('Unknown data format'));
        }
        $reader = new Xlsx();
        if (! $spreadsheet = $reader->load($filePath)) {
            $this->error(__('Unknown data format'));
        }
        $currentSheet = $spreadsheet->getSheet(0);  // 读取文件中的第一个工作表
        $allColumn = $currentSheet->getHighestDataColumn();  // 取得最大的列号
        $allRow = $currentSheet->getHighestRow();  // 取得一共有多少行
        $maxColumnNumber = Coordinate::columnIndexFromString($allColumn);  // 取得最大的列数字
        if ($allRow <= 2) {
        // if ($allRow <= 1) {
            $this->error(__('No rows were updated'));
        }
        $firstHead = $currentSheet->getCellByColumnAndRow(1, 2)->getValue();
        // $firstHead = $currentSheet->getCellByColumnAndRow(1, 1)->getValue();
        if ($firstHead !== '订单编号') {
            $this->error(__('数据表头不对'));
        }

        $counter = [];
        try {
            // 获取数据
            $dataList = [];
            for ($currentRow = 3; $currentRow <= $allRow; $currentRow++) {
            // for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) {
                $values = [];
                for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
                    $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
                    $values[] = is_null($val) ? '' : trim($val);
                }
                $dataList[] = $values;
            }

            // 设置标题
            $this->setSheetCellValue($currentSheet, -1, '导入结果');
            $currentSheet->getCellByColumnAndRow(9, 2)->getStyle()->applyFromArray([
                'font'      => [
                    'name'  => 'Arial',
                    'color' => ['rgb' => '000000'],
                    'size'  => 12,
                    'bold'  => true
                ],
                'alignment' => [
                    'horizontal' => Alignment::HORIZONTAL_CENTER,
                    'vertical'   => Alignment::VERTICAL_CENTER,
                ]
            ]);

            // 处理数据
            // 列对应关系：0=订单ID，1=收件人，2=手机号，3=收货地址，4=领取方式，5=快递公司，6=快递单号，7=快递手机号
            $expressCompany = Logic::queryExpressCompany();
            $expressNameMap = array_flip($expressCompany);
            foreach ($dataList as $index => $item) {
                if (empty($item[0])) {
                    $this->setSheetCellValue($currentSheet, $index, '首列为空', 1, $counter);
                    continue;
                }
                if (! $giftOrder = GiftOrder::get(['number' => $item[0]])) {
                    $this->setSheetCellValue($currentSheet, $index, '订单不存在', 1, $counter);
                    continue;
                }
                if ($giftOrder->gift_data_array['type'] != GiftMain::TYPE_1) {
                    $this->setSheetCellValue($currentSheet, $index, '只支持实物发货', 1, $counter);
                    continue;
                }
                if ($giftOrder->status == GiftOrder::STATUS_HAS_BACK) {
                    $this->setSheetCellValue($currentSheet, $index, '订单已取消', 1, $counter);
                    continue;
                }
                if ($item[4] === '快递邮寄') {
                    if ($giftOrder->express_number != $item[6]) {
                        $giftOrder->deployed_at = time();
                    }
                    $giftOrder->gain_method = GiftOrder::GAIN_METHOD_EXPRESS;
                    if (! in_array($item[5], $expressCompany)) {
                        $this->setSheetCellValue($currentSheet, $index, '快递公司不对', 1, $counter);
                        continue;
                    }
                    $giftOrder->express_company = $expressNameMap[$item[5]];
                    if (empty($item[6])) {
                        $this->setSheetCellValue($currentSheet, $index, '快递单号不能为空', 1, $counter);
                        continue;
                    }
                    $giftOrder->express_number = $item[6];
                    if (empty($item[7])) {
                        if ($item[5] === '顺丰速递') {
                            $this->setSheetCellValue($currentSheet, $index, '顺丰速递需要填写快递手机号', 1, $counter);
                            continue;
                        }
                    }
                    $giftOrder->express_phone = $item[7];
                } elseif ($item[4] === '线下领取') {
                    if ($giftOrder->gain_method != GiftOrder::GAIN_METHOD_SELF) {
                        $giftOrder->deployed_at = time();
                    }
                    $giftOrder->gain_method = GiftOrder::GAIN_METHOD_SELF;
                } else {
                    $this->setSheetCellValue($currentSheet, $index, '领取方式不对', 1, $counter);
                    continue;
                }
                $first = $giftOrder->status == GiftOrder::STATUS_WAIT_DEPLOY;
                $giftOrder->status = GiftOrder::STATUS_HAS_DEPLOY;
                $giftOrder->save();
                if ($first) {
                    Logic::sendDeployMessage($giftOrder->id);  // 发送发货消息
                    $this->setSheetCellValue($currentSheet, $index, '发货成功', 0, $counter);
                } else {
                    $this->setSheetCellValue($currentSheet, $index, '更新发货', 0, $counter);
                }
            }

            // 生成excel文件
            $filePath = DS . 'uploads' . DS . date('Ymd') . DS . Random::alnum(32) . '.xlsx';
            $objWriter = IOFactory::createWriter($spreadsheet, 'Xlsx');
            $objWriter->save(ROOT_PATH . 'public' . $filePath);

            // 更新导入结果
            ImportLogModel::update([
                'result_file' => $filePath,
                'status'      => ImportLogModel::STATUS_FINISH
            ], [
                'scene'       => ImportLogModel::SCENE_GIFT_DEPLOY,
                'import_file' => $file,
            ]);
        } catch (Exception $exception) {
            $this->error($exception->getMessage());
        }

        // 导入结果
        $content = ['处理成功<br>'];
        foreach ($counter as $key => $value) {
            $hasError = false;
            if (! in_array($key, ['发货成功', '更新发货信息'])) {
                $key .= '，导入失败';
                $hasError = true;
            }
            $cont = $key . '： ' . $value . '条';
            if ($hasError) {
                $cont = '<b style="color: yellow;">' . $cont . '</b>';
            }
            $content[] = $cont;
        }
        $content = implode('<br>', $content);

        $exportResult = $filePath;
        $content .= '<br><br><a href="' . $exportResult . '" target="_blank" style="color: yellow;"><b><i class="fa fa-download"></i> 下载导入结果</b></a>';

        $this->success($content);
    }

    /**
     * 设置表格内容
     *
     * @param $workSheet
     * @param $index
     * @param $value
     */
    private function setSheetCellValue(&$workSheet, $index, $value, $level = 0, &$counter = [])
    {
        if ($level != -1) {
            Super::counter($counter, $value);
        }
        if ($oldValue = $workSheet->getCellByColumnAndRow(9, $index + 3)->getValue()) {
            $value = $oldValue . '；' . $value;
        }
        $workSheet->setCellValueByColumnAndRow(9, $index + 3, $value);
        if (! $oldValue) {
            $workSheet->getCellByColumnAndRow(9, $index + 3)->getStyle()->applyFromArray([
                'font'      => [
                    'name'  => 'Arial',
                    'color' => ['rgb' => $level > 0 ? 'f75544' : '000000'],
                    'size'  => 12,
                ],
                'alignment' => [
                    'horizontal' => Alignment::HORIZONTAL_CENTER,
                    'vertical'   => Alignment::VERTICAL_CENTER,
                ]
            ]);
        }
    }

    // 导出数据
    public function export()
    {
        // 超时、超内存设置
        ini_set('memory_limit', '1024M');
        ini_set('max_execution_time', '0');

        if ($this->request->isPost()) {
            // 重载查询条件
            $search = $this->request->post('search');
            $ids = $this->request->post('ids');
            $filter = $this->request->post('filter');
            $op = $this->request->post('op');
            $columns = $this->request->post('columns');
            list($filter, $op) = $this->formatFilterOp($filter, $op);

            // 初始化表
            $spreadsheet = new Spreadsheet();
            $worksheet = $spreadsheet->setActiveSheetIndex(0);
            $worksheet->getDefaultRowDimension()->setRowHeight(25);  // 设置默认行高
            $worksheet->getDefaultColumnDimension()->setAutoSize(true);  // 设置自动宽

            // 设置标题
            foreach ([
                         'ID',
                         '订单编号',
                         '订单类型',
                         '订单来源',
                         '卡号',
                         '礼品',
                         '价值',
                         '规格',
                         '领取方式',
                         '收件人',
                         '手机号',
                         '收货地址',
                         '备注',
                         '状态',
                         '兑换时间',
                         '快递公司',
                         '快递单号',
                         '快递手机号'
                     ] as $key => $value) {
                $worksheet->setCellValueByColumnAndRow($key + 1, 1, __($value));
                $worksheet->getCellByColumnAndRow($key + 1, 1)->getStyle()->applyFromArray([
                    'font'      => [
                        'name'  => 'Arial',
                        'color' => ['rgb' => '000000'],
                        'size'  => 12,
                        'bold'  => true
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_CENTER,
                        'vertical'   => Alignment::VERTICAL_CENTER,
                    ]
                ]);
            }
            $worksheet->getColumnDimensionByColumn(1)->setWidth(20);  // 设置题目宽度

            // 获取条件
            $whereIds = $ids === 'all' ? '1=1' : ['gift_order.id' => ['in', explode(',', $ids)]];
            $this->request->get(['search' => $search, 'ids' => $ids, 'filter' => $filter, 'op' => $op]);
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();

            $expressInfos = json_decode(Constant::EXPRESS_INFOS, true);

            // 查询数据
            $row = 1;
            $this->model
                ->where($where)
                ->with('cardCodeData')
                ->where($whereIds)
                ->chunk(100, function ($items) use (&$row, &$worksheet, $expressInfos) {
                    foreach ($items as $item) {
                        $row++;
                        $col = 1;
                        $values = Super::arrayGetSet($item, [
                            'id',
                            'number'         => function ($item) {
                                return $item->number . ' ';
                            },
                            'type'           => 'typeText',
                            'source'         => function ($item) {
                                return $item->model_text;
                            },
                            'card_number'         => function ($item) {
                                if ($item->cardCodeData) {
                                    $cardNumber = $item->cardCodeData->number;
                                } else {
                                    $cardNumber = '-';
                                }
                                return $cardNumber;
                            },
                            'gift_name'      => function ($item) {
                                return $item->giftDataArray['name'];
                            },
                            // 价值
                            'gift_worth' => function ($item) {
                                return $item->giftDataArray['worth'];
                            },
                            'gift_spec_name' => function ($item) {
                                return $item->giftDataArray['spec_data']['name'] ?? '无';
                            },
                            'gain_method'    => 'gainMethodText',
                            'name',
                            'phone',
                            'address'        => function ($item) {
                                if ($item->gain_method == GiftOrder::GAIN_METHOD_EXPRESS) {
                                    // return $item->province . ', ' . $item->city . ', ' . $item->area . ', ' . $item->address;
                                    return $item->province . $item->city . $item->area . $item->address;
                                }

                                return '';
                            },
                            'note',
                            'status'         => 'statusText',
                            'created_at'     => function ($item) {
                                return date('Y-m-d H:i:s', $item->created_at);
                            },
                            'express_company' => function ($item) use ($expressInfos) {
                                if (!empty($item->express_company)) {
                                    return isset($expressInfos[$item->express_company]) ? $expressInfos[$item->express_company] : '未知快递公司' . $item->express_company; 
                                }
                                return '';
                            },
                            'express_number' => function ($item) {
                                return $item->express_number . ' ';
                            },
                            'express_phone',
                        ]);
                        foreach ($values as $value) {
                            $worksheet->setCellValueByColumnAndRow($col, $row, $value);
                            $worksheet->getStyleByColumnAndRow($col, $row)->getNumberFormat()
                                ->setFormatCode(NumberFormat::FORMAT_TEXT);
                            $worksheet->getCellByColumnAndRow($col, $row)->getStyle()->applyFromArray([
                                'alignment' => [
                                    'horizontal' => Alignment::HORIZONTAL_CENTER,
                                    'vertical'   => Alignment::VERTICAL_CENTER,
                                ]
                            ]);
                            $col++;
                        }
                    }
                });

            // 导出文件
            // Redirect output to a client’s web browser (Excel2007)
            $fileName = date('YmdHis');
            header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
            header('Content-Disposition: attachment;filename="' . $fileName . '.xlsx"');
            header('Cache-Control: max-age=0');
            // If you're serving to IE 9, then the following may be needed
            header('Cache-Control: max-age=1');
            // If you're serving to IE over SSL, then the following may be needed
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');  // always modified
            header('Cache-Control: cache, must-revalidate');  // HTTP/1.1
            header('Pragma: public');  // HTTP/1.0
            $objWriter = IOFactory::createWriter($spreadsheet, 'Xlsx');
            $objWriter->save('php://output');
            exit;
        }
    }
}
